package org.javaboy.shiro.realm;

import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.PasswordMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.javaboy.shiro.mapper.UserMapper;
import org.javaboy.shiro.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Set;

/**
 * Realm 叫做用户视图，其实就是在 Realm 中返回用户数据，可以理解为一个 UserMapper
 */
@Component
public class MyRealm extends AuthorizingRealm {
    @Autowired
    UserMapper userMapper;

    /**
     * 当用户登录的时候，subject.login 方法最终就会调用到这里
     *
     * @param token 这个参数就是 login 方法传入的参数，这个参数里边包含了用户登录时候填写的 username 和 password
     * @return 返回值就是从数据库中查询出来的用户信息
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        //这就是用户登录时候输入的用户名
        String username = usernamePasswordToken.getUsername();
        //根据用户名去数据库中查询用户的完整信息
        User user = userMapper.getUserByUsername(username);
        if (user == null) {
            throw new UnknownAccountException("账户不存在");
        }
        //如果用户名输入正确，那么就查询到 user 对象，接下来将 user 对象封装为 AuthenticationInfo 返回
        //注意，第二个参数是数据库查询出来的用户密码，不是用户登录时候输入的用户密码
        return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());
    }

    @Override
    public CredentialsMatcher getCredentialsMatcher() {
        return new PasswordMatcher();
    }

    /**
     * 这个方法是用来返回用户权限信息的
     * 用户的角色和权限都可以在这个方法中返回
     * @param principals the primary identifying principals of the AuthorizationInfo that should be retrieved.
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("doGetAuthorizationInfo");
        //获取当前登录成功的用户名
        String username = (String) principals.getPrimaryPrincipal();
        //根据用户名去数据库中查询用户的角色和权限
        Set<String> roles = userMapper.getUserRolesByUsername(username);
        Set<String> perms = userMapper.getUserPermsByUsername(username);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
        info.setStringPermissions(perms);
        return info;
    }
}
